package com.entrogy.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.entrogy.bean.*;
import com.entrogy.dao.ClassMapper;
import com.entrogy.dao.StudentAttendanceMapper;
import com.entrogy.service.StudentAttendanceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ClassName StudentAttendanceServiceImpl
 * @Description
 * @Author luoxingjiang
 * @Date 2019/7/17 0017 上午 10:51
 * @Version 1.0
 **/
@Service
public class StudentAttendanceServiceImpl implements StudentAttendanceService {


    @Autowired
    private StudentAttendanceMapper studentAttendanceMapper;

    @Autowired
    private ClassMapper classMapper;

    @Override
    public GradeAttendanceTimeEntity getGradeMorningAttendanceTime(Integer schoolCode, Integer gradeId) {
        return studentAttendanceMapper.getGradeMorningAttendanceTime(schoolCode, gradeId);
    }

    @Override
    public boolean addGradeAttendanceInfo(GradeAttendanceTimeEntity gradeAttendanceTime) {
        int row = studentAttendanceMapper.addGradeAttendanceInfo(gradeAttendanceTime);
        return true;
    }

    @Override
    public boolean updateGradeAttendanceInfo(List<GradeAttendanceTimeEntity> gradeAttendanceTime) {
        int row = studentAttendanceMapper.updateGradeAttendanceInfo(gradeAttendanceTime);
        return true;
    }

    @Override
    public List<ClassAttendanceEntity> listClassMorningAttendanceInfo(List<Integer> classIds, Date time, Integer schoolCode) {
        List<ClassAttendanceEntity> classAttendanceList = new ArrayList<>();

        String dynArrangeTableName = "dyn_arrange" + new SimpleDateFormat("yyyyMMdd").format(time);

        for (int i = 0; i < classIds.size(); i++) {
            Integer classId = classIds.get(i);
            ClassAttendanceEntity classAttendance = getClassBasicAttendanceInfo(classId, time, schoolCode);
            // 早上时段类型为1
            if (!isArriveAttendanceTime(1, classId, schoolCode, null, time)) {
                // 没有到该年级的考勤时间的话直接返回基本信息，并提示未到该班级的考勤时间
                classAttendanceList.add(classAttendance);
                continue;
            }
            // 查找该班级早上的考勤时段
            JSONObject startTimeAndEndTime = studentAttendanceMapper.getClassMorningAttendanceTime(classId, schoolCode);
            // 如果startTimeAndEndTime为空则该班级所在年级没有设置早上的考勤时间
            if (startTimeAndEndTime == null) {
                classAttendanceList.add(classAttendance);
                continue;
            }
            // 查找在晚上需要回家但是早上的考勤时段内没有在大门的设备通行记录的学生人数，
            // 他们都属于考勤异常人员，通过student_information表中的allow_time字段判别走读的时段，
            // 000表示住校生，010下午回去，001晚上回去，以此类推
            String startTime = startTimeAndEndTime.getString("startTime");
            String endTime = startTimeAndEndTime.getString("endTime");
            String tableName = getTableNameBySelectTime(time);
            // 查询请假学生id
            List<Integer> askForLeaveStudentIds = studentAttendanceMapper.countAskForLeaveStudent(classId, time, schoolCode, null);

            // 查询中午的考勤时段，用于现在早上统计的时间限制
            String noonAttendanceTimeFrame = getClassAttendanceTimeFrame(2, classId, schoolCode, dynArrangeTableName);
            String[] temp = noonAttendanceTimeFrame.split("-");
            // 拼接要统计的中午的考勤时间段
            String noonStartTime = temp[0] + ":00";

            // 查询考勤异常学生id
            Map<String, Object> map = separateMorningExceptionStudent(classId, schoolCode, startTime, endTime, tableName, askForLeaveStudentIds, noonStartTime);
            int lateStudentCount = ((List<Integer>) map.get("lateStudentIdList")).size();
            classAttendance.setLateStudentCount(lateStudentCount);
            int noAttendanceCount = ((List<Integer>) map.get("noAttendanceStudentIdList")).size();
            classAttendance.setNoAttendanceCount(noAttendanceCount);
            // 实到人数为总人数减去迟到人数再减去请假人数再减去未考勤人数
            classAttendance.setActualAttendance(classAttendance.getTotalStudentCount() - classAttendance.getLateStudentCount() - classAttendance.getAskForLeaveStudentCount() - classAttendance.getNoAttendanceCount());
            classAttendanceList.add(classAttendance);
        }
        return classAttendanceList;
    }

    /**
     * 分类返回早上考勤异常学生id
     *
     * @param classId
     * @param schoolCode
     * @param startTime
     * @param endTime
     * @param tableName
     * @param noonStartTime
     * @return
     */
    private Map<String, Object> separateMorningExceptionStudent(Integer classId, Integer schoolCode, String startTime, String endTime, String tableName, List<Integer> askForLeaveStudentIds, String noonStartTime) {
        List<Integer> exceptionStudentIdList = studentAttendanceMapper.countMorningLateStudentByNoPassRecord(classId, schoolCode, startTime, endTime, tableName, null, noonStartTime);
        // 查找在晚上需要回家但是早上的考勤时段内在大门的设备有迟到通行记录的学生id（统计时间段是中午考勤开始时间之前）
        List<Integer> lateStudentIdList = studentAttendanceMapper.countMorningLateStudentPassRecord(classId, schoolCode, startTime, endTime, tableName, null, noonStartTime);
        List<Integer> noAttendanceStudentIdList = new ArrayList<>();
        // 将考勤异常学生中未考勤学生筛选出来
        for (Integer exceptionStudentId : exceptionStudentIdList) {
            if (!lateStudentIdList.contains(exceptionStudentId)) {
                noAttendanceStudentIdList.add(exceptionStudentId);
            }
        }
        // 迟到人数应该排除请假人数
        lateStudentIdList = deleteDuplicateStuId(lateStudentIdList, askForLeaveStudentIds);
        // 未考勤学生人数应该排除请假人数
        noAttendanceStudentIdList = deleteDuplicateStuId(noAttendanceStudentIdList, askForLeaveStudentIds);
        Map<String, Object> map = new HashMap<>();
        map.put("lateStudentIdList", lateStudentIdList);
        map.put("noAttendanceStudentIdList", noAttendanceStudentIdList);
        return map;
    }

    @Override
    public List<ClassAttendanceEntity> listClassNoonOrAfternoonAttendanceInfo(List<Integer> classIds, Date time, Integer schoolCode, Integer timeFrameType) {
        List<ClassAttendanceEntity> classAttendanceList = new ArrayList<>();
        for (int i = 0; i < classIds.size(); i++) {
            Integer classId = classIds.get(i);
            // 得到班级基本信息，包括班级名字，应到人数以及请假人数
            ClassAttendanceEntity classAttendance = getClassBasicAttendanceInfo(classId, time, schoolCode);
            // 查找该班级中午和下午的考勤时段,首先根据查询的时间生成该班级的考勤时间表名
            String dynArrangeTableName = "dyn_arrange" + new SimpleDateFormat("yyyyMMdd").format(time);
            // 如果查询的是中午的考勤记录，那就查询该班级中午的考勤时间段，如果是下午的话就查询下午
            String startTimeAndEndTime = getClassAttendanceTimeFrame(timeFrameType, classId, schoolCode, dynArrangeTableName);
            if (!isArriveAttendanceTime(timeFrameType, classId, schoolCode, dynArrangeTableName, time)) {
                classAttendanceList.add(classAttendance);
                continue;
            }
            // 如果startTimeAndEndTime为空则该班级所在年级没有设置中午或者下午的考勤时间
            if (startTimeAndEndTime == null) {
                classAttendanceList.add(classAttendance);
                continue;
            }
            String[] temp = startTimeAndEndTime.split("-");
            // 拼接要统计的中午的考勤时间段
            String startTime = temp[0] + ":00";
            String endTime = temp[1] + ":00";
            // 得到查询时间的流水记录对应的表名
            String tableName = getTableNameBySelectTime(time);

            /**
             * 中午和晚上的考勤记录新增分类：分为迟到人数和未考勤人数
             * 迟到人数定义：通行时段内出行设备只有一条通行记录的人数并且有一条在通行时段外有一条进门记录的人数，或者通行时段内出行设备和进入设备次数为单数的人数并且在通行时段外有一条进门记录的人数
             * 未考勤人数定义：通行时段内出行设备只有一条通行记录的人数，或者通行时段内出行设备和进入设备次数为单数的人数
             */
            Map<String, Object> map = getNoDuplicExceptionStudentId(timeFrameType, classId, schoolCode, startTime, endTime, tableName, null);
            Integer lateStudentCount = (Integer) map.get("lateStudentCount");
            Integer noAttendanceCount = (Integer) map.get("noAttendanceCount");
            List<Integer> lateStudentIdList = (List<Integer>) map.get("lateStudentIdList");
            List<Integer> noAttendanceStudentIdList = (List<Integer>) map.get("noAttendanceStudentIdList");
            // 迟到学生id应该排除请假学生id
            if (classAttendance.getAskForLeaveStudentCount() > 0) {
                List<Integer> askForLeaveStudentIds = studentAttendanceMapper.countAskForLeaveStudent(classId, time, schoolCode, null);
                // 如果两个集合完全相等则没有迟到学生
                if (askForLeaveStudentIds.equals(lateStudentIdList)) {
                    classAttendance.setLateStudentCount(0);
                }
                // 判断请假学生和迟到学生的重合个数
                // 重合个数
                int count = 0;
                for (Integer studentId : askForLeaveStudentIds) {
                    if (lateStudentIdList.contains(studentId)) {
                        count++;
                    }
                }
                if (count > 0) {
                    // 如果请假学生和迟到学生id有重合那么需要排除
                    classAttendance.setLateStudentCount(lateStudentCount - count);
                } else {
                    // 没有重合的话就不需要排除
                    classAttendance.setLateStudentCount(lateStudentCount);
                }
            } else {
                classAttendance.setLateStudentCount(lateStudentCount);
            }

            // 未考勤人数应该排除请假人数
            if (classAttendance.getAskForLeaveStudentCount() > 0) {
                List<Integer> askForLeaveStudentIds = studentAttendanceMapper.countAskForLeaveStudent(classId, time, schoolCode, null);
                // 如果两个集合完全相等则没有未考勤学生
                if (askForLeaveStudentIds.equals(noAttendanceStudentIdList)) {
                    classAttendance.setNoAttendanceCount(0);
                }
                // 判断请假学生和迟到学生的重合个数
                int count = 0;
                for (Integer studentId : askForLeaveStudentIds) {
                    if (noAttendanceStudentIdList.contains(studentId)) {
                        count++;
                    }
                }
                if (count > 0) {
                    // 如果请假学生和未考勤学生id有重合那么需要排除
                    classAttendance.setNoAttendanceCount(noAttendanceCount - count);
                } else {
                    // 没有重合的话就不需要排除
                    classAttendance.setNoAttendanceCount(noAttendanceCount);
                }
            } else {
                classAttendance.setNoAttendanceCount(noAttendanceCount);
            }

            // 实到人数为总人数减去迟到人数再减去请假人数再减去为考勤人数
            classAttendance.setActualAttendance(classAttendance.getTotalStudentCount() - classAttendance.getLateStudentCount() - classAttendance.getAskForLeaveStudentCount() - classAttendance.getNoAttendanceCount());
            classAttendanceList.add(classAttendance);
        }
        return classAttendanceList;
    }

    /**
     * 将通行记录异常的学生id分别统计
     *
     * @param tableName
     * @param endTime
     * @param exceptionId
     * @param lateStudentCount
     * @param noAttendanceCount
     * @return
     */
    private Map<String, Object> separateExceptionId(String tableName, String endTime, List<Integer> exceptionId, Integer lateStudentCount, Integer noAttendanceCount) {
        // 考勤迟到学生id
        List<Integer> lateStudentIdList = new ArrayList<>();
        List<Integer> noAttendanceStudentIdList = new ArrayList<>();
        Date passEndTime = new Date();
        try {
            passEndTime = new SimpleDateFormat("yyyyMMddHH:mm:ss").parse(tableName.substring(11) + endTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        for (Integer studentId : exceptionId) {
            int passCount = studentAttendanceMapper.listStudentPassRecord(studentId, passEndTime, tableName).size();
            if (passCount > 0) {
                lateStudentIdList.add(studentId);
                lateStudentCount++;
            } else {
                noAttendanceStudentIdList.add(studentId);
                noAttendanceCount++;
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("lateStudentCount", lateStudentCount);
        map.put("noAttendanceCount", noAttendanceCount);
        map.put("lateStudentIdList", lateStudentIdList);
        map.put("noAttendanceStudentIdList", noAttendanceStudentIdList);
        return map;
    }

    @Override
    public Map<String, Object> getMorningAttendanceDetailInfo(Integer classId, Date time, Integer schoolCode, Integer gradeId) {
        Map<String, Object> classMorningAttendanceDetailInfo = new HashMap<>();
        // 查询请假学生详情
        List<Integer> askForLeaveStudentIds = studentAttendanceMapper.countAskForLeaveStudent(classId, time, schoolCode, gradeId);
        List<AskForLeaveStudentEntity> askForLeaveStudentList = new ArrayList<>();
        if (askForLeaveStudentIds.size() > 0) {
            askForLeaveStudentList = studentAttendanceMapper.listAskForLeaveStudentInfo(askForLeaveStudentIds, time);
        }
        classMorningAttendanceDetailInfo.put("askForLeaveStudentList", askForLeaveStudentList);
        if (classId != null) {
            // 早上时段类型为1
            if (!isArriveAttendanceTime(1, classId, schoolCode, null, time)) {
                classMorningAttendanceDetailInfo.put("lateStudentList", null);
                classMorningAttendanceDetailInfo.put("noAttendanceStudentList", null);
            } else {
                Map<String, Object> map = getMorningClassAttendanceExceptionInfo(classId, schoolCode, gradeId, time, askForLeaveStudentIds);
                classMorningAttendanceDetailInfo.put("lateStudentList", map == null ? null : map.get("lateStudentList"));
                classMorningAttendanceDetailInfo.put("noAttendanceStudentList", map == null ? null : map.get("noAttendanceStudentList"));
            }
        } else {
            List<Integer> classIdList = classMapper.listClassIdBySchoolCode(schoolCode, gradeId);
            List<AttendanceExceptionStudentEntity> gradeOrSchoolLateStudentList = new ArrayList<>();
            List<AttendanceExceptionStudentEntity> gradeOrSchoolNoAttendanceStudentList = new ArrayList<>();
            for (Integer classId1 : classIdList) {
                Map<String, Object> map = getMorningClassAttendanceExceptionInfo(classId1, schoolCode, gradeId, time, askForLeaveStudentIds);
                gradeOrSchoolLateStudentList.addAll(map == null ? new ArrayList<>() : (List<AttendanceExceptionStudentEntity>) map.get("lateStudentList"));
                gradeOrSchoolNoAttendanceStudentList.addAll(map == null ? new ArrayList<>() : (List<AttendanceExceptionStudentEntity>) map.get("noAttendanceStudentList"));
            }
            classMorningAttendanceDetailInfo.put("lateStudentList", gradeOrSchoolLateStudentList);
            classMorningAttendanceDetailInfo.put("noAttendanceStudentList", gradeOrSchoolNoAttendanceStudentList);
        }
        return classMorningAttendanceDetailInfo;
    }


    /**
     * 查询早上某个班级的考勤异常（迟到和未考勤）学生信息
     *
     * @param classId
     * @param schoolCode
     * @param gradeId
     * @param time
     * @param askForLeaveStudentIds
     * @return
     */
    private Map<String, Object> getMorningClassAttendanceExceptionInfo(Integer classId, Integer schoolCode, Integer gradeId, Date time, List<Integer> askForLeaveStudentIds) {
        // 查找该班级早上的考勤时段
        JSONObject startTimeAndEndTime = studentAttendanceMapper.getClassMorningAttendanceTime(classId, schoolCode);
        if (startTimeAndEndTime == null) {
            return null;
        }
        // 如果startTimeAndEndTime为空则该班级所在年级没有设置早上的考勤时间 TODO 可能要返回未设置早上考勤的年级列表
        String startTime = startTimeAndEndTime.getString("startTime");
        String endTime = startTimeAndEndTime.getString("endTime");
        String tableName = getTableNameBySelectTime(time);

        String dynArrangeTableName = "dyn_arrange" + new SimpleDateFormat("yyyyMMdd").format(time);
        // 查询中午的考勤时段，用于现在早上统计的时间限制
        String noonAttendanceTimeFrame = getClassAttendanceTimeFrame(2, classId, schoolCode, dynArrangeTableName);
        String[] temp = noonAttendanceTimeFrame.split("-");
        // 拼接要统计的中午的考勤时间段
        String noonStartTime = temp[0] + ":00";

        Map<String, Object> map = separateMorningExceptionStudent(classId, schoolCode, startTime, endTime, tableName, askForLeaveStudentIds, noonStartTime);
        List<Integer> lateStudentIdList = (List<Integer>) map.get("lateStudentIdList");
        List<Integer> noAttendanceStudentIdList = (List<Integer>) map.get("noAttendanceStudentIdList");

        List<AttendanceExceptionStudentEntity> lateStudentList = new ArrayList<>();
        List<AttendanceExceptionStudentEntity> noAttendanceStudentList = new ArrayList<>();
        if (lateStudentIdList.size() > 0) {
            lateStudentList = studentAttendanceMapper.listAttendanceExceptionStudentInfo(lateStudentIdList, tableName, endTime, noonStartTime);
        }
        if (noAttendanceStudentIdList.size() > 0) {
            noAttendanceStudentList = studentAttendanceMapper.listAttendanceExceptionStudentInfo(noAttendanceStudentIdList, tableName, endTime, noonStartTime);
        }
        Map<String, Object> map1 = new HashMap<>();
        map1.put("lateStudentList", lateStudentList);
        map1.put("noAttendanceStudentList", noAttendanceStudentList);
        return map1;
    }

    @Override
    public Map<String, Object> getNoonOrAfternoonAttendanceDetailInfo(Integer classId, Date time, Integer schoolCode, Integer timeFrameType, Integer gradeId) {
        Map<String, Object> classNoonOrAfternoonAttendanceDetailInfo = new HashMap<>();
        // 查询请假学生详情
        List<Integer> askForLeaveStudentIds = studentAttendanceMapper.countAskForLeaveStudent(classId, time, schoolCode, gradeId);
        List<AskForLeaveStudentEntity> askForLeaveStudentList = new ArrayList<>();
        if (askForLeaveStudentIds.size() > 0) {
            askForLeaveStudentList = studentAttendanceMapper.listAskForLeaveStudentInfo(askForLeaveStudentIds, time);
        }
        classNoonOrAfternoonAttendanceDetailInfo.put("askForLeaveStudentList", askForLeaveStudentList);
        String dynArrangeTableName = "dyn_arrange" + new SimpleDateFormat("yyyyMMdd").format(time);
        // 查找该班级中午和下午的考勤时段,首先根据查询的时间生成该班级的考勤时间表名
//        if (!isArriveAttendanceTime(timeFrameType, classId, schoolCode, dynArrangeTableName, time)){
//            classNoonOrAfternoonAttendanceDetailInfo.put("lateStudentList", null);
//            classNoonOrAfternoonAttendanceDetailInfo.put("noAttendanceStudentList", null);
//        }else {
        // 查询考勤异常学生详情
        if (classId != null) {
            Map<String, Object> map = getNoonOrAfternoonClassExceptionInfo(timeFrameType, classId, schoolCode, dynArrangeTableName, time, gradeId, askForLeaveStudentIds);
            classNoonOrAfternoonAttendanceDetailInfo.put("lateStudentList", map == null ? null : map.get("lateStudentList"));
            classNoonOrAfternoonAttendanceDetailInfo.put("noAttendanceStudentList", map == null ? null : map.get("noAttendanceStudentList"));
        } else {
            List<Integer> classIdList = classMapper.listClassIdBySchoolCode(schoolCode, gradeId);
            List<AttendanceExceptionStudentEntity> gradeOrSchoolLateStudentList = new ArrayList<>();
            List<AttendanceExceptionStudentEntity> gradeOrSchoolNoAttendanceStudentList = new ArrayList<>();
            for (Integer classId1 : classIdList) {
                if (!isArriveAttendanceTime(timeFrameType, classId1, schoolCode, dynArrangeTableName, time)) {
                    gradeOrSchoolLateStudentList.addAll(new ArrayList<>());
                    gradeOrSchoolNoAttendanceStudentList.addAll(new ArrayList<>());
                    continue;
                }
                Map<String, Object> map = getNoonOrAfternoonClassExceptionInfo(timeFrameType, classId1, schoolCode, dynArrangeTableName, time, gradeId, askForLeaveStudentIds);
                gradeOrSchoolLateStudentList.addAll(map == null ? new ArrayList<>() : (List<AttendanceExceptionStudentEntity>) map.get("lateStudentList"));
                gradeOrSchoolNoAttendanceStudentList.addAll(map == new ArrayList<>() ? null : (List<AttendanceExceptionStudentEntity>) map.get("noAttendanceStudentList"));
            }
            classNoonOrAfternoonAttendanceDetailInfo.put("lateStudentList", gradeOrSchoolLateStudentList);
            classNoonOrAfternoonAttendanceDetailInfo.put("noAttendanceStudentList", gradeOrSchoolNoAttendanceStudentList);
        }
//        }
        return classNoonOrAfternoonAttendanceDetailInfo;
    }

    /**
     * 查询中午和下午某个班级的考勤异常（迟到和未考勤）学生信息
     *
     * @param classId
     * @param schoolCode
     * @param gradeId
     * @param time
     * @param askForLeaveStudentIds
     * @return
     */
    private Map<String, Object> getNoonOrAfternoonClassExceptionInfo(Integer timeFrameType, Integer classId, Integer schoolCode, String dynArrangeTableName, Date time, Integer gradeId, List<Integer> askForLeaveStudentIds) {
        Map<String, Object> map1 = new HashMap<>();
        // 如果查询的是中午的考勤记录，那就查询该班级中午的考勤时间段，如果是下午的话就查询下午
        String startTimeAndEndTime = getClassAttendanceTimeFrame(timeFrameType, classId, schoolCode, dynArrangeTableName);
        // 如果startTimeAndEndTime为空则该班级所在年级没有设置中午或者下午的考勤时间
        if (startTimeAndEndTime == null) {
            return null;
        }
        String[] temp = startTimeAndEndTime.split("-");
        // 拼接要统计的中午的考勤时间段
        String startTime = temp[0] + ":00";
        String endTime = temp[1] + ":00";
        String tableName = getTableNameBySelectTime(time);

        Map<String, Object> map = getNoDuplicExceptionStudentId(timeFrameType, classId, schoolCode, startTime, endTime, tableName, gradeId);
        List<Integer> lateStudentIdList = (List<Integer>) map.get("lateStudentIdList");
        List<Integer> noAttendanceStudentIdList = (List<Integer>) map.get("noAttendanceStudentIdList");
        List<AttendanceExceptionStudentEntity> lateStudentList = new ArrayList<>();
        List<AttendanceExceptionStudentEntity> noAttendanceStudentList = new ArrayList<>();
        if (lateStudentIdList.size() > 0) {
            lateStudentIdList = deleteDuplicateStuId(lateStudentIdList, askForLeaveStudentIds);
            lateStudentList = studentAttendanceMapper.listAttendanceExceptionStudentInfo(lateStudentIdList, tableName, endTime, null);
        }
        if (noAttendanceStudentIdList.size() > 0) {
            noAttendanceStudentIdList = deleteDuplicateStuId(noAttendanceStudentIdList, askForLeaveStudentIds);
            noAttendanceStudentList = studentAttendanceMapper.listAttendanceExceptionStudentInfo(noAttendanceStudentIdList, tableName, endTime, null);
        }
        map1.put("lateStudentList", lateStudentList);
        map1.put("noAttendanceStudentList", noAttendanceStudentList);
        return map1;
    }

    private Map<String, Object> getNoDuplicExceptionStudentId(Integer timeFrameType, Integer classId, Integer schoolCode, String startTime, String endTime, String tableName, Integer gradeId) {
        Integer lateStudentCount = 0;
        Integer noAttendanceCount = 0;

        // 中午考勤异常学生id（包括迟到和未考勤学生，单次记录）
        List<Integer> noonExceptionIdListForOnePassRecord;
        // 下午考勤异常学生id（包括迟到和未考勤学生，单次记录）
        List<Integer> afternoonExceptionIdListForOnePassRecord;
        // 中午考勤异常学生id（包括迟到和未考勤学生，奇次记录）
        List<Integer> noonExceptionIdListForOddPassRecord;
        // 下午考勤异常学生id（包括迟到和未考勤学生，奇次记录）
        List<Integer> afternoonExceptionIdListForOddPassRecord;

        // 中午考勤迟到学生id
        List<Integer> noonLateIdListForOnePassRecord = new ArrayList<>();
        // 下午考勤迟到学生id
        List<Integer> afternoonLateIdListForOnePassRecord = new ArrayList<>();
        // 中午考勤迟到学生id
        List<Integer> noonLateIdListForOddPassRecord = new ArrayList<>();
        // 下午考勤迟到学生id
        List<Integer> afternoonLateIdListForOddPassRecord = new ArrayList<>();

        // 中午未考勤学生id
        List<Integer> noonNoAttendanceIdListForOnePassRecord = new ArrayList<>();
        // 下午未考勤学生id
        List<Integer> afternoonNoAttendanceIdListForOnePassRecord = new ArrayList<>();
        // 中午未考勤学生id
        List<Integer> noonNoAttendanceIdListForOddPassRecord = new ArrayList<>();
        // 下午未考勤学生id
        List<Integer> afternoonNoAttendanceIdListForOddPassRecord = new ArrayList<>();

        if (timeFrameType == 2) {
            // 得到中午要出去的学生但是在中午考勤时段内只有一条在出门设备上通行记录的学生id即考勤异常学生id
            noonExceptionIdListForOnePassRecord = studentAttendanceMapper.countClassNoonLateStudentByHasOnePassRecord(classId, schoolCode, startTime, endTime, tableName, null);
            // 对这些考勤异常的学生进行分类，查询他们在通行时间段内是否进校，有进校记录则为迟到，否则为未考勤
            Map<String, Object> map = separateExceptionId(tableName, endTime, noonExceptionIdListForOnePassRecord, lateStudentCount, noAttendanceCount);
            lateStudentCount = (Integer) map.get("lateStudentCount");
            noAttendanceCount = (Integer) map.get("noAttendanceCount");
            noonLateIdListForOnePassRecord = (List<Integer>) map.get("lateStudentIdList");
            noonNoAttendanceIdListForOnePassRecord = (List<Integer>) map.get("noAttendanceStudentIdList");

            // 出行设备和进入设备次数为单数的人数 TODO 此处需要校验出门次数是否大于进门次数
            noonExceptionIdListForOddPassRecord = studentAttendanceMapper
                    .countClassNoonLateStudentByHasOddPassRecord(classId, schoolCode, startTime, endTime, tableName, null);
            Map<String, Object> map1 = separateExceptionId(tableName, endTime, noonExceptionIdListForOddPassRecord, lateStudentCount, noAttendanceCount);
            lateStudentCount = (Integer) map1.get("lateStudentCount");
            noAttendanceCount = (Integer) map1.get("noAttendanceCount");
            noonLateIdListForOddPassRecord = (List<Integer>) map1.get("lateStudentIdList");
            afternoonNoAttendanceIdListForOnePassRecord = (List<Integer>) map1.get("noAttendanceStudentIdList");
        } else if (timeFrameType == 3) {
            // 得到下午要出去的学生但是在下午考勤时段内只有一条在出门设备上通行记录的学生人数即迟到人数
            afternoonExceptionIdListForOnePassRecord = studentAttendanceMapper.countClassAfterNoonLateStudentByHasOnePassRecord(classId, schoolCode, startTime, endTime, tableName, null);
            // 对这些考勤异常的学生进行分类，查询他们在通行时间段内是否进校，有进校记录则为迟到，否则为未考勤
            Map<String, Object> map = separateExceptionId(tableName, endTime, afternoonExceptionIdListForOnePassRecord, lateStudentCount, noAttendanceCount);
            lateStudentCount = (Integer) map.get("lateStudentCount");
            noAttendanceCount = (Integer) map.get("noAttendanceCount");
            afternoonLateIdListForOnePassRecord = (List<Integer>) map.get("lateStudentIdList");
            noonNoAttendanceIdListForOddPassRecord = (List<Integer>) map.get("noAttendanceStudentIdList");

            // 出行设备和进入设备次数为单数的人数
            afternoonExceptionIdListForOddPassRecord = studentAttendanceMapper
                    .countClassAfternoonLateStudentByHasOddPassRecord(classId, schoolCode, startTime, endTime, tableName, null);
            Map<String, Object> map1 = separateExceptionId(tableName, endTime, afternoonExceptionIdListForOddPassRecord, lateStudentCount, noAttendanceCount);
            lateStudentCount = (Integer) map1.get("lateStudentCount");
            noAttendanceCount = (Integer) map1.get("noAttendanceCount");
            afternoonLateIdListForOddPassRecord = (List<Integer>) map1.get("lateStudentIdList");
            afternoonNoAttendanceIdListForOddPassRecord = (List<Integer>) map1.get("noAttendanceStudentIdList");
        }

        List<Integer> lateStudentIdList = new ArrayList<>();
        lateStudentIdList.addAll(noonLateIdListForOnePassRecord);
        lateStudentIdList.addAll(afternoonLateIdListForOnePassRecord);
        lateStudentIdList.addAll(noonLateIdListForOddPassRecord);
        lateStudentIdList.addAll(afternoonLateIdListForOddPassRecord);

        List<Integer> noAttendanceStudentIdList = new ArrayList<>();
        noAttendanceStudentIdList.addAll(noonNoAttendanceIdListForOnePassRecord);
        noAttendanceStudentIdList.addAll(afternoonNoAttendanceIdListForOnePassRecord);
        noAttendanceStudentIdList.addAll(noonNoAttendanceIdListForOddPassRecord);
        noAttendanceStudentIdList.addAll(afternoonNoAttendanceIdListForOddPassRecord);
        Map<String, Object> map = new HashMap<>();
        map.put("lateStudentIdList", lateStudentIdList);
        map.put("noAttendanceStudentIdList", noAttendanceStudentIdList);
        map.put("lateStudentCount", lateStudentCount);
        map.put("noAttendanceCount", noAttendanceCount);
        return map;
    }


    @Override
    public List<GradeEntity> getGradeList(Integer schoolCode) {
        return studentAttendanceMapper.listGrade(schoolCode);
    }


    /**
     * 返回要查询的时间的流水记录的表名
     *
     * @return
     */
    private String getTableNameBySelectTime(Date time) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        return "pass_record" + dateFormat.format(time);
    }

    /**
     * 得到班级基本考勤信息，包括班级名字，应到人数，以及请假人数
     *
     * @param classId
     * @param time
     * @param schoolCode
     * @return
     */
    private ClassAttendanceEntity getClassBasicAttendanceInfo(Integer classId, Date time, Integer schoolCode) {
        // 得到班级基本信息，包括班级名字，应到人数
        ClassAttendanceEntity classAttendance = studentAttendanceMapper.getClassInfo(classId, schoolCode);
        // 得到班级的请假人数
        int askForLeaveStudentCount = studentAttendanceMapper.countAskForLeaveStudent(classId, time, schoolCode, null).size();
        // 班级应到人数 = 班级总人数
        classAttendance.setShouldAttendance(classAttendance.getTotalStudentCount());
        classAttendance.setAskForLeaveStudentCount(askForLeaveStudentCount);
        return classAttendance;
    }

    /**
     * 请假学生和迟到学生的去重
     *
     * @param lateStudentIds
     * @param askForLeaveStudentIds
     * @return
     */
    private List<Integer> deleteDuplicateStuId(List<Integer> lateStudentIds, List<Integer> askForLeaveStudentIds) {
        Iterator iterator = lateStudentIds.iterator();
        // 取出请假学生的id
        while (iterator.hasNext()) {
            Integer lateStudentId = (Integer) iterator.next();
            if (askForLeaveStudentIds.contains(lateStudentId)) {
                iterator.remove();
            }
        }
        return lateStudentIds;
    }

    /**
     * 查询不同时段的考勤时间
     *
     * @param timeFrameType
     * @param classId
     * @param schoolCode
     * @param dynArrangeTableName
     * @return
     */
    @Override
    public String getClassAttendanceTimeFrame(Integer timeFrameType, Integer classId, Integer schoolCode, String dynArrangeTableName) {
        String startTimeAndEndTime = null;
        if (timeFrameType == 2) {
            startTimeAndEndTime = studentAttendanceMapper.getClassNoonAttendanceTime(classId, schoolCode, dynArrangeTableName);
        } else if (timeFrameType == 3) {
            startTimeAndEndTime = studentAttendanceMapper.getClassAfternoonAttendanceTime(classId, schoolCode, dynArrangeTableName);
        }
        return startTimeAndEndTime;
    }

    @Override
    public String getGradeAttendanceTimeFrame(Integer timeFrameType, Integer gradeId, Integer schoolCode, String dynArrangeTableName) {
        String startTimeAndEndTime = null;
        if (timeFrameType == 2) {
            startTimeAndEndTime = studentAttendanceMapper.getGradeNoonAttendanceTime(gradeId, schoolCode, dynArrangeTableName);
        } else if (timeFrameType == 3) {
            startTimeAndEndTime = studentAttendanceMapper.getGradeAfternoonAttendanceTime(gradeId, schoolCode, dynArrangeTableName);
        }
        return startTimeAndEndTime;
    }

    @Override
    public boolean isArriveGradeAttendanceTime(Integer timeFrameType, Integer gradeId, Integer schoolCode, String dynArrangeTableName, Date time) {
        String endTime = null;
        if (timeFrameType == 2 || timeFrameType == 3) {
            String startTimeAndEndTime = getGradeAttendanceTimeFrame(timeFrameType, gradeId, schoolCode, dynArrangeTableName);
            if (startTimeAndEndTime == null) {
                return false;
            }
            String temp[] = startTimeAndEndTime.split("-");
            if (temp.length == 2) {
                endTime = startTimeAndEndTime.split("-")[1];
            }
        }
        if (timeFrameType == 1) {
            GradeAttendanceTimeEntity gradeAttendance = getGradeMorningAttendanceTime(schoolCode, gradeId);
            if (gradeAttendance == null) {
                return false;
            }
            endTime = gradeAttendance.getEndTime();
        }
        if (endTime == null) {
            return false;
        }
        // 当前时间
        Calendar now = Calendar.getInstance();
        // 当前班主任或者年级组长查看考勤的考勤时段的结束时间，
        String nowTime = now.get(Calendar.HOUR_OF_DAY) + ":" + now.get(Calendar.MINUTE);
        // 当前时间必须大于结束时间才能够查看统计
        if (nowTime.compareTo(endTime) > 0) {
            return true;
        }
        return false;
    }


    /**
     * 判断是否到达该时段的考勤统计时间 需要到达考勤时间才能够查看该时段的考勤记录
     *
     * @param timeFrameType
     * @param classId
     * @param schoolCode
     * @param dynArrangeTableName
     * @param time
     * @return
     */
    @Override
    public boolean isArriveAttendanceTime(Integer timeFrameType, Integer classId, Integer schoolCode, String dynArrangeTableName, Date time) {
        String endTime = null;
        if (timeFrameType == 2 || timeFrameType == 3) {
            String startTimeAndEndTime = getClassAttendanceTimeFrame(timeFrameType, classId, schoolCode, dynArrangeTableName);
            if (startTimeAndEndTime == null) {
                return false;
            }
            String temp[] = startTimeAndEndTime.split("-");
            if (temp.length == 2) {
                endTime = startTimeAndEndTime.split("-")[1];
            }
        }
        if (timeFrameType == 1) {
            JSONObject jsonObject = studentAttendanceMapper.getClassMorningAttendanceTime(classId, schoolCode);
            if (jsonObject == null) {
                return false;
            }
            endTime = jsonObject.getString("endTime");
        }
        if (endTime == null) {
            return false;
        }
        // 当前时间
        Calendar now = Calendar.getInstance();
        // 当前班主任或者年级组长查看考勤的考勤时段的结束时间，
        Calendar attendanceEndTime = Calendar.getInstance();
        attendanceEndTime.setTime(time);
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        Date date = null;
        try {
            date = sdf.parse(endTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar temp = Calendar.getInstance();
        temp.setTime(date);
        attendanceEndTime.set(Calendar.HOUR_OF_DAY, temp.get(Calendar.HOUR_OF_DAY));
        attendanceEndTime.set(Calendar.MINUTE, temp.get(Calendar.MINUTE));
        attendanceEndTime.set(Calendar.SECOND, temp.get(Calendar.SECOND));
        // 当前时间必须大于结束时间才能够查看统计
        if (now.after(attendanceEndTime)) {
            return true;
        }
        return false;
    }
}
